#include "RenderObject.h"
RenderObject::RenderObject(CompName cid,string s,Mesh::sPtr mesh,RenderMode m)
	:Component(cid),
	m_name(s),
	m_mode(m),
	m_mesh(mesh),
	m_vertexLayout(NULL),
	m_defaultSampler(NULL),
	m_effect()
{
}

RenderObject::~RenderObject()
{
}

void RenderObject::AddedToObject()
{
}

string RenderObject::GetName()
{
	return m_name;
}


ID3D11Buffer* RenderObject::CreateVertexBuffer(Vertices* vertices,Texs* texs)
{
	ID3D11Buffer* buffer=NULL;
	try
	{
		if(vertices==NULL&&texs==NULL)
			EXCEPTION("")
		D3D11_BUFFER_DESC bufferDesc;
		ZeroMemory( &bufferDesc, sizeof( bufferDesc ) );
		D3D11_SUBRESOURCE_DATA initData;
		ZeroMemory( &initData, sizeof( initData ) );
		VertexTexStr* tmpVertexTex=NULL;
		bufferDesc.Usage=D3D11_USAGE_DYNAMIC;
		bufferDesc.BindFlags=D3D11_BIND_VERTEX_BUFFER;
		bufferDesc.CPUAccessFlags=D3D11_CPU_ACCESS_WRITE;
		bufferDesc.MiscFlags=0;
		bufferDesc.StructureByteStride=0;
		switch(m_mode)
		{
		case RenderWithCameraWithTexture:
			bufferDesc.ByteWidth=sizeof(VertexTexStr)*vertices->size();
			tmpVertexTex=new VertexTexStr[vertices->size()];
			for(size_t i=0;i<vertices->size();i++)
			{
				tmpVertexTex[i].pos=(*vertices)[i];
				tmpVertexTex[i].tex=(*texs)[i];
			}
			initData.pSysMem=tmpVertexTex;
			
			SendMessage(MSG_CREATE_BUFFER,AuxGroupArgus(&bufferDesc,&initData,&buffer));
			delete[] tmpVertexTex;
			break;
		case RenderWithCameraNoTexture:
			EXCEPTION("")
		//	bufferDesc.ByteWidth=sizeof(float)*6*m_vertices->size();
		//	VertexColorStr* tmpVertices=new VertexColorStr[m_vertices->size()];
		//	XMCOLOR red(255,0,0,0);
		//	for(size_t i=0;i<m_vertices->size();i++)
		//	{
		//		tmpVertices[i].pos=(*m_vertices)[i];
		//		tmpVertices[i].color=red;
		//	}
		//	initData.pSysMem=&tmpVertices;
		//	
		//	SendMessage(MSG_CREATE_BUFFER,AuxGroupArgus(&bufferDesc,&initData,&m_verticesBuffer));
		//	delete[] tmpVertices;
		//	break;
		}
	}
	catch(boost::bad_any_cast& e)
	{
		PRINT_BOOST_ERROR(e)
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}

	return buffer;

}

ID3D11Buffer* RenderObject::CreateIndexBuffer(Indexs* indexs)
{
	ID3D11Buffer* buffer=NULL;
	try
	{
		D3D11_BUFFER_DESC bufferDesc;
		D3D11_SUBRESOURCE_DATA initData;
		ZeroMemory(&bufferDesc,sizeof(bufferDesc));
		ZeroMemory(&initData,sizeof(initData));
		bufferDesc.ByteWidth=sizeof(unsigned int)*indexs->size();
		bufferDesc.Usage=D3D11_USAGE_DEFAULT;
		bufferDesc.BindFlags=D3D11_BIND_INDEX_BUFFER;
		bufferDesc.CPUAccessFlags=0;
		bufferDesc.MiscFlags=0;
		bufferDesc.StructureByteStride=0;
		initData.pSysMem=(void*)&((*indexs)[0]);
		SendMessage(MSG_CREATE_BUFFER,AuxGroupArgus(&bufferDesc,&initData,&buffer));
	}
	catch(boost::bad_any_cast& e)
	{
		PRINT_BOOST_ERROR(e)
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
	return buffer;
}

ID3D11SamplerState* RenderObject::CreateSamplerState()
{
	ID3D11SamplerState* sampler=NULL;
	D3D11_SAMPLER_DESC samplerDesc;
    ZeroMemory( &samplerDesc, sizeof( samplerDesc ) );
    samplerDesc.AddressU = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressV = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.AddressW = D3D11_TEXTURE_ADDRESS_WRAP;
    samplerDesc.ComparisonFunc = D3D11_COMPARISON_NEVER;
    samplerDesc.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR;
    samplerDesc.MaxLOD = D3D11_FLOAT32_MAX;
	SendMessage(MSG_CREATE_SAMPLER,AuxGroupArgus(&samplerDesc,&sampler));
	return sampler;
}

void RenderObject::Initial(const boost::shared_ptr<Effect>& effect)
{
	m_effect=effect;
	switch(m_mode)
	{
	case RenderWithCameraWithTexture:
		{
			SendMessage(MSG_CREATE_INPUT_LAYOUT,
				AuxGroupArgus(
					m_effect->GetLayoutDesc("DefaultTechniqueWithCameraWithTexture"),
					m_effect->GetVertexShaderDesc("DefaultTechniqueWithCameraWithTexture"),
					&m_vertexLayout
				)
			);
			m_defaultSampler=CreateSamplerState();
				
			Mesh::SubMeshPtr tmpSubMeshs=m_mesh->GetSubMeshs();

			for(Mesh::SubMesh::iterator iter=tmpSubMeshs->begin();iter!=tmpSubMeshs->end();iter++)
			{
				RenderObjectStr* tmp=new RenderObjectStr;
				tmp->verticesBuffer=CreateVertexBuffer((*iter)->vertices,(*iter)->texs);
				tmp->vertices=(*iter)->vertices;
				tmp->indexsBuffer=CreateIndexBuffer((*iter)->indexs);
				tmp->samplerState=m_defaultSampler;
				tmp->texture=(*iter)->texture;
				tmp->texs=(*iter)->texs;
				tmp->numIndexs=(*iter)->indexs->size();
				m_renderObjs.push_back(tmp);
			}
		}
		break;
	case RenderWithCameraNoTexture:
		EXCEPTION("")
			break;
	default:
		break;
	}
}

void RenderObject::UpdatePreFrame(const int incr)
{
	if(m_mesh->GetMeshUsage()==MESH_ANIM)
	{
		CalcAnim(incr);
		for(RenderObjsIter iter=m_renderObjs.begin();iter!=m_renderObjs.end();iter++)
		{
			size_t size=(*iter)->vertices->size();
			VertexTexStr* tmpVertexTex=new VertexTexStr[size];
			for(size_t i=0;i<size;i++)
			{
				tmpVertexTex[i].pos=(*(*iter)->vertices)[i];
				tmpVertexTex[i].tex=(*(*iter)->texs)[i];
			}
			SendMessage(MSG_UPDATE_BUFFER,AuxGroupArgus((*iter)->verticesBuffer,(void*)tmpVertexTex,size*sizeof(VertexTexStr)));
			delete[] tmpVertexTex;
		}
	}
}
		
void RenderObject::Render()
{

	if(!m_effect)
		EXCEPTION("")
		
	unsigned int stride;
	unsigned int offset;
	if(m_mode==RenderWithCameraWithTexture)
		stride = sizeof(VertexTexStr);
	else if(m_mode==RenderWithCameraNoTexture)
		stride = sizeof(VertexColorStr);
	else
		EXCEPTION("")
	offset = 0;
		
	try
	{
		SendMessage(MSG_SET_IL,AuxGroupArgus(m_vertexLayout));
		for(RenderObjsIter iter=m_renderObjs.begin();iter!=m_renderObjs.end();iter++)
		{
			SendMessage(MSG_SET_VB,AuxGroupArgus(0,1,(*iter)->verticesBuffer,&stride,&offset));
			SendMessage(MSG_SET_IB,AuxGroupArgus((*iter)->indexsBuffer,DXGI_FORMAT_R32_UINT,0u));
	
			switch(m_mode)
			{
			case RenderWithCameraWithTexture:
				{
					XMMATRIX worldMatrix=GetWorldMatrix();
					m_effect->SetMatrix("WorldMatrix",worldMatrix);
					SendMessage(MSG_SET_PT,AuxGroupArgus(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST));
					m_effect->SetResource("DefaultTexture",(*iter)->texture);
					m_effect->SetSampler("DefaultSampler",m_defaultSampler);
					m_effect->Apply("DefaultTechniqueWithCameraWithTexture");
					SendMessage(MSG_DI,AuxGroupArgus((*iter)->numIndexs,0u,0));
					break;
				}
			case RenderWithCameraNoTexture:
				break;
			}
		}
	}
	catch(boost::bad_any_cast& e)
	{
		PRINT_BOOST_ERROR(e)
	}
	catch(std::exception& e)
	{
		PRINT_ERROR(e)
	}
}
